Flutter Packages and Dependencies
Flutter packages and dependencies allow developers to extend the functionality of Flutter applications without building every feature from scratch. Packages can provide networking, state management, database access, animations, device features, authentication, UI components, utilities, and many other capabilities.
Flutter uses the Dart package manager, Pub, to manage packages and their dependencies. Packages are commonly discovered through pub.dev and declared in the project's pubspec.yaml file.
1. What is a Flutter Package?
A package is reusable code that can be added to a Flutter or Dart project. A package can contain Dart libraries, resources, tests, images, fonts, examples, and its own dependencies.
Packages help developers reuse functionality instead of implementing common features from the beginning.
Examples of Package Use Cases
- Making HTTP/API requests
- Opening URLs
- Displaying network images
- State management
- Firebase integration
- Local database access
- Animations
- Device features
- Permission management
- Date and time formatting
- JSON serialization
- Charts and graphs
2. What is a Flutter Plugin?
A plugin is a special type of package that provides access to platform-specific functionality. Plugins can connect Flutter code with Android, iOS, web, Windows, macOS, or Linux platform APIs.
For example, a camera plugin can provide access to the device camera while Flutter code interacts with the plugin through a Dart API.
| Package | Plugin |
|---|
| Primarily provides reusable Dart functionality. | Provides Dart APIs that can also communicate with platform-specific functionality. |
| May work without native platform code. | Often contains platform-specific implementations. |
| Example: utility or data-processing package. | Example: camera, battery, or device integration plugin. |
3. What is a Dependency?
A dependency is an external package or library that an application requires to provide certain functionality.
For example, if an application needs to make HTTP requests, it can declare an HTTP package as a dependency.
dependencies:
http: ^1.0.0
The application can then import and use the package in Dart code.
4. What is pub.dev?
pub.dev is the package repository used by the Dart and Flutter ecosystem. Developers can search for packages, review their documentation, inspect versions, check supported platforms, and learn how to install them.
When Selecting a Package, Check
- Package purpose
- Current and previous versions
- Supported platforms
- Flutter/Dart compatibility
- Documentation quality
- Dependencies
- Repository activity
- Example usage
- License
- Known issues
5. The pubspec.yaml File
Every Flutter project contains a pubspec.yaml file. It stores project metadata and configuration, including package dependencies.
Basic Example
name: my_flutter_app
description: A Flutter application
environment:
sdk: ^3.0.0
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.0
http: ^1.0.0
dev_dependencies:
flutter_test:
sdk: flutter
The indentation in YAML is significant. Incorrect indentation can cause configuration errors.
6. dependencies Section
The dependencies section contains packages required by the application at runtime.
dependencies:
flutter:
sdk: flutter
http: ^1.0.0
provider: ^6.0.0
In this example, Flutter, HTTP functionality, and Provider are application dependencies.
7. dev_dependencies Section
The dev_dependencies section contains packages mainly required during development, testing, analysis, or code generation.
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^6.0.0
Testing and linting packages commonly belong in this section.
8. Adding a Package with flutter pub add
The recommended command-line approach for adding a package is flutter pub add.
flutter pub add http
This command adds the dependency to the project's pubspec.yaml and resolves the package.
Example
flutter pub add provider
flutter pub add shared_preferences
flutter pub add image_picker
9. Adding a Package Manually
You can also add a package directly to pubspec.yaml.
dependencies:
flutter:
sdk: flutter
http: ^1.0.0
provider: ^6.0.0
After changing the file, run:
flutter pub get
10. What Does flutter pub get Do?
flutter pub get resolves and downloads the dependencies required by the project according to the dependency constraints.
flutter pub get
Typical Workflow
- Add a package to
pubspec.yaml.
- Run
flutter pub get.
- Import the package in Dart code.
- Use the package APIs.
- Run and test the application.
11. Importing a Package
After adding a package, import its Dart library into the required file.
import 'package:http/http.dart' as http;
The exact import path depends on the package's documentation and public libraries.
12. Complete Package Example Using http
Step 1: Add the Package
flutter pub add http
Step 2: Import the Package
import 'package:http/http.dart' as http;
Step 3: Make a Request
Future fetchData() async {
final response = await http.get(
Uri.parse('https://example.com/data'),
);
if (response.statusCode == 200) {
print(response.body);
} else {
print('Request failed');
}
}
13. Package Version Numbers
Packages use semantic versioning conventions such as:
1.2.3
- 1 = major version
- 2 = minor version
- 3 = patch version
| Version | Meaning |
|---|
| 1.0.0 | Specific release version |
| ^1.0.0 | Compatible versions within the allowed major-version range |
| >=1.0.0 <2.0.0 | Explicit version range |
| any | Allows any available version matching other constraints |
14. Caret Syntax
Caret syntax is commonly used to specify a compatible version range.
dependencies:
http: ^1.0.0
This allows Pub's version solver to select a compatible release within the permitted range rather than requiring one exact version.
15. Exact Version vs Version Range
Exact Version
http: 1.0.0
This requests exactly version 1.0.0.
Version Range
http: ^1.0.0
A version range gives Pub more flexibility when resolving compatible dependencies.
16. pubspec.lock
The pubspec.lock file records the concrete versions selected by Pub for the project's direct and transitive dependencies.
pubspec.yaml
↓
Dependency Constraints
↓
Pub Version Solver
↓
pubspec.lock
↓
Resolved Package Versions
For Flutter applications, the lockfile is normally committed to version control so that team members and build systems can reproduce the same resolved dependency versions.
17. Direct Dependencies
A direct dependency is a package that you explicitly declare in your project's pubspec.yaml.
dependencies:
http: ^1.0.0
provider: ^6.0.0
Here, http and provider are direct dependencies.
18. Transitive Dependencies
A transitive dependency is a package required by another dependency. You may not declare it directly, but it is still part of the application's dependency graph.
Your App
↓
Package A
↓
Package B
↓
Package C
If your application directly depends on Package A and Package A depends on Package B, Package B is a transitive dependency of your application.
19. Dependency Resolution
Pub uses a version solver to find a compatible set of package versions. The application cannot compile with two different versions of the same Dart package in its dependency graph.
Application
↓
Package A ──→ common_package ^2.0.0
↓
Package B ──→ common_package ^2.1.0
↓
Pub resolves a compatible version
If the constraints cannot be satisfied together, Pub reports a dependency resolution conflict.
20. Understanding Dependency Conflicts
A conflict can occur when two packages require incompatible versions of the same dependency.
Example
Package A:
common_package: ^2.0.0
Package B:
common_package: ^3.0.0
If no single version satisfies both constraints, dependency resolution fails.
Possible Solutions
- Upgrade one of the packages.
- Use compatible versions.
- Replace an outdated package.
- Review the dependency tree.
- Use a dependency override only when appropriate.
21. dependency_overrides
dependency_overrides can force a particular dependency version during resolution.
dependencies:
package_a: ^1.0.0
package_b: ^2.0.0
dependency_overrides:
common_package: 2.5.0
Overrides should be used carefully because forcing a version can create runtime or compile-time incompatibilities if the dependent packages were not designed for that version.
22. Updating Dependencies
To resolve newer package versions that are allowed by the constraints in pubspec.yaml, use:
flutter pub upgrade
This is different from upgrading the Flutter SDK itself.
23. Checking Outdated Dependencies
You can inspect the project's dependency status using Pub commands.
flutter pub outdated
This helps identify packages that have newer versions available and shows how current constraints affect upgrades.
24. Removing a Package
Use flutter pub remove to remove a package from the project.
flutter pub remove http
The dependency is removed from the project's dependency configuration.
25. Path Dependencies
A package can be loaded from a local directory using a path dependency. This is useful when developing multiple local packages together.
dependencies:
my_shared_package:
path: ../my_shared_package
Example Structure
projects/
├── shopping_app/
└── shared_package/
The Flutter application can reference the neighboring package using the relative path.
26. Git Dependencies
A dependency can also be obtained from a Git repository.
dependencies:
my_package:
git:
url: https://github.com/example/my_package.git
Git dependencies can be useful for packages that are not published to pub.dev or when testing a particular repository version.
27. Git Dependency with a Specific Reference
A Git dependency can specify a branch, tag, or commit reference.
dependencies:
my_package:
git:
url: https://github.com/example/my_package.git
ref: main
Pinning a Git dependency to a known reference can help make builds more predictable.
28. Git Package Inside a Repository Folder
If the package is not located at the root of a Git repository, a package path can be specified.
dependencies:
my_package:
git:
url: https://github.com/example/packages.git
path: packages/my_package
29. Flutter SDK Dependencies
Some packages are provided directly by the Flutter SDK.
Flutter
dependencies:
flutter:
sdk: flutter
Flutter Test
dev_dependencies:
flutter_test:
sdk: flutter
Flutter Localizations
dependencies:
flutter_localizations:
sdk: flutter
30. Common Flutter Packages
| Package Type | Example | Typical Purpose |
|---|
| Networking | http | HTTP requests |
| State Management | provider | Application state management |
| Local Storage | shared_preferences | Simple persistent key-value data |
| Images | image_picker | Selecting images from device sources |
| URLs | url_launcher | Opening external URLs and supported platform destinations |
| Firebase | FlutterFire packages | Firebase services |
| Routing | go_router | Application navigation and routing |
| Dates | intl | Internationalization and date/number formatting |
31. Adding Multiple Packages
Several packages can be added to the same project.
flutter pub add http
flutter pub add provider
flutter pub add shared_preferences
flutter pub add intl
Each package is then available through its corresponding Dart import.
32. Example Project with Dependencies
name: shopping_app
environment:
sdk: ^3.0.0
dependencies:
flutter:
sdk: flutter
http: ^1.0.0
provider: ^6.0.0
shared_preferences: ^2.0.0
intl: ^0.19.0
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^6.0.0
33. Using Package APIs
Adding a dependency does not automatically mean that its functionality is used. You normally import the required library and then call the package's APIs.
import 'package:http/http.dart' as http;
Future loadData() async {
final response = await http.get(
Uri.parse('https://example.com'),
);
print(response.statusCode);
}
34. Package Assets and Resources
Packages can contain resources such as images, fonts, examples, and other files. Flutter applications can also declare their own assets through the flutter section of pubspec.yaml.
flutter:
uses-material-design: true
assets:
- assets/images/
- assets/icons/
Always follow the package's documentation when accessing resources provided by a package.
35. Package Compatibility
Before installing a package, check whether it supports the platforms required by your application.
| Platform | What to Check |
|---|
| Android | Android SDK and plugin compatibility |
| iOS | iOS deployment target and native dependencies |
| Web | Web support and browser limitations |
| Windows | Windows desktop support |
| macOS | macOS desktop support |
| Linux | Linux desktop support |
36. Native Plugin Considerations
Some plugins include platform-specific code. When such a plugin is added, the native portion may need to be compiled into the application. In some cases, a full application restart is required instead of relying only on hot reload or hot restart.
If a plugin reports a MissingPluginException, verify that the plugin is correctly installed, the application was rebuilt when necessary, and the plugin supports the platform being used.
37. Package Documentation
Always read the package documentation before integrating a package into a production application.
Useful Information to Look For
- Installation instructions
- Required configuration
- Import statements
- Basic usage examples
- Platform requirements
- Permissions
- Breaking changes
- Known limitations
- Migration instructions
38. Package Security and Maintenance
Third-party dependencies become part of your application's technology stack. Before using a package, consider whether it is actively maintained and whether its dependencies and permissions are appropriate for your project.
Good Practices
- Use packages from trusted sources.
- Read the package documentation.
- Review package dependencies.
- Keep important packages reasonably up to date.
- Test package upgrades before releasing them.
- Remove unused packages.
- Avoid unnecessary dependencies.
- Review permissions required by plugins.
39. Package Upgrade Workflow
Check current dependencies
↓
flutter pub outdated
↓
Review available updates
↓
Update pubspec constraints
↓
flutter pub get / flutter pub upgrade
↓
Run tests
↓
Test application
↓
Build application
↓
Release after verification
40. Removing Unused Dependencies
Unused dependencies can make projects harder to maintain. If a package is no longer required, remove it.
flutter pub remove package_name
After removing a package, search the source code to ensure that its imports and related configuration are no longer required.
41. Packages and Project Architecture
Packages should support the architecture of the application rather than make the architecture unnecessarily complicated.
Flutter Application
│
├── UI
├── State Management
├── Business Logic
├── Repository
├── Services
└── External Packages
├── Networking
├── Storage
├── Firebase
└── Device APIs
42. Packages in a Real Flutter Application
A production application may use several types of packages together.
User Interface
↓
State Management Package
↓
Repository
↓
Networking Package
↓
Remote API
UI
↓
Storage Service
↓
Local Storage Package
The important goal is to keep dependencies organized and ensure that each package has a clear purpose.
43. Example: API Application Dependencies
pubspec.yaml
dependencies:
flutter:
sdk: flutter
http: ^1.0.0
Dart Code
import 'dart:convert';
import 'package:http/http.dart' as http;
Future> fetchUsers() async {
final response = await http.get(
Uri.parse('https://example.com/users'),
);
if (response.statusCode == 200) {
return jsonDecode(response.body) as List;
}
throw Exception('Failed to load users');
}
44. Example: State Management Dependency
A state-management package can be added when state needs to be shared across multiple widgets.
flutter pub add provider
After installation, the package can be imported:
import 'package:provider/provider.dart';
The exact architecture should depend on the size and requirements of the application.
45. Example: Local Storage Dependency
A local storage package can be used when an application needs to persist simple data such as preferences or settings.
flutter pub add shared_preferences
Example import:
import 'package:shared_preferences/shared_preferences.dart';
46. Dependency Management Commands
| Command | Purpose |
|---|
flutter pub add package_name | Add a dependency |
flutter pub get | Resolve and retrieve dependencies |
flutter pub upgrade | Upgrade dependencies within allowed constraints |
flutter pub outdated | Check dependency update status |
flutter pub remove package_name | Remove a dependency |
flutter pub deps | Display the dependency tree |
47. Viewing the Dependency Tree
The flutter pub deps command helps you understand direct and transitive dependencies.
flutter pub deps
This can be useful when investigating why a package is present or when debugging dependency conflicts.
48. Common Dependency Problems
Problem 1: Package Not Found
Check the package name, spelling, network connection, and package availability.
Problem 2: Version Conflict
Review the constraints of the packages involved and determine whether compatible versions are available.
Problem 3: Import Error
Make sure the dependency has been added and flutter pub get has completed successfully.
Problem 4: Plugin Not Working
Check platform support and perform a full rebuild when the plugin contains native platform code.
Problem 5: Build Failure After Upgrade
Review the package changelog, migration instructions, platform requirements, and dependency constraints.
49. Best Practices for Flutter Dependencies
- Use only packages that provide meaningful value to the application.
- Prefer well-documented packages.
- Check package compatibility with your target platforms.
- Use version constraints instead of unnecessarily restrictive exact versions.
- Keep dependencies reasonably up to date.
- Test dependency upgrades before production releases.
- Commit
pubspec.yaml and the appropriate lockfile for application projects.
- Remove unused dependencies.
- Avoid unnecessary dependency overrides.
- Understand transitive dependencies when troubleshooting.
- Read migration notes before major package upgrades.
- Keep package responsibilities clear within the application architecture.
50. Practical Mini Project
Project: Flutter Package Demo App
Create a Flutter application that demonstrates multiple packages and dependency-management concepts.
Suggested Features
- Fetch data from an API using an HTTP package.
- Display the response in a list.
- Store a simple preference locally.
- Use a state-management package for shared UI state.
- Display loading and error states.
- Navigate between multiple screens.
- Organize dependencies in
pubspec.yaml.
Suggested Workflow
Create Flutter Project
↓
Select Required Packages
↓
Add Packages
↓
flutter pub get
↓
Import Packages
↓
Implement Features
↓
Test
↓
Check Dependencies
↓
Build Application
51. Interview Questions
Q1. What is a package in Flutter?
A package is reusable Dart or Flutter code that can be added to an application to provide functionality without implementing everything from scratch.
Q2. What is a plugin?
A plugin is a type of package that can expose platform-specific functionality to Flutter applications.
Q3. What is pubspec.yaml?
pubspec.yaml is the project's configuration file that contains metadata, dependencies, environment constraints, and other project configuration.
Q4. What is flutter pub get?
It resolves and retrieves the dependencies declared by the project.
Q5. What is pubspec.lock?
It records the concrete dependency versions selected by Pub for the project.
Q6. What is a transitive dependency?
A transitive dependency is a dependency required indirectly through another package.
Q7. What is dependency_overrides?
It allows a project to force a particular dependency version during dependency resolution. It should be used carefully.
Q8. What is a path dependency?
A path dependency references a package stored in a local file-system directory.
Q9. What is a Git dependency?
A Git dependency references a package stored in a Git repository.
Q10. Why should package versions be managed carefully?
Package versions can affect compatibility, dependency resolution, APIs, and application behavior. Controlled dependency management helps maintain stable builds.
52. Quick Revision
- Flutter supports reusable packages from the Dart and Flutter ecosystem.
- Packages are commonly discovered on pub.dev.
- Plugins are packages that can expose platform-specific functionality.
- Dependencies are declared in
pubspec.yaml.
dependencies contains runtime dependencies.
dev_dependencies contains development and testing dependencies.
flutter pub add adds a package.
flutter pub get resolves and retrieves dependencies.
flutter pub upgrade updates dependencies within allowed constraints.
flutter pub outdated helps inspect available updates.
flutter pub remove removes a dependency.
pubspec.lock records resolved package versions.
- Direct dependencies are explicitly declared by the application.
- Transitive dependencies are required indirectly.
- Path and Git dependencies can be used for unpublished packages.
- Dependency conflicts occur when version constraints cannot be satisfied together.
- Dependencies should be selected, updated, and tested carefully.
53. Learning Outcome
After completing this topic, you should be able to understand Flutter packages and plugins, search for suitable packages, add and remove dependencies, work with pubspec.yaml, understand version constraints, use flutter pub commands, identify direct and transitive dependencies, handle dependency conflicts, and organize external packages in a Flutter project.
54. JustAcademy Flutter Resources
Learn more about Flutter development through the JustAcademy Flutter Training Course.
You can also Register for Flutter Course Demo to explore the training program.
55. Summary
Flutter packages and dependencies are an important part of modern Flutter development. They allow developers to reuse existing functionality, integrate platform features, communicate with APIs, manage application state, store data, and build applications faster. The pubspec.yaml file defines project dependencies, while Pub resolves compatible versions and records the selected versions in pubspec.lock. Proper dependency selection, version management, testing, and maintenance help keep Flutter applications reliable and maintainable.